/// \file AppLogic.h
/// \date 2012-12-08
/// \brief application logic class
#ifndef _TORUSPRORENDERING_APPMODEL_APPLOGIC_H__
#define _TORUSPRORENDERING_APPMODEL_APPLOGIC_H__

#include <Render/Include/IWinWindow.h>
#include <Render/Include/Renderer.h>

#include <AppModel/Include/Semaphore.h>
#include <AppModel/Include/Task.h>
#include <AppModel/Include/TimeMeter.h>
#include <AppModel/Include/Torus.h>

#define TASK_TIME_STEP 20

#define ANGLE_STEP 0.314f
#define RADIO_STEP 0.5f

namespace AppModel
{
/// \brief application logic class
class AppLogic
{
public:
    /// \brief enum used to indicate user's input
    typedef enum
    {
        RIGHT_ARROW_PRESSED,
        LEFT_ARROW_PRESSED,
        UP_ARROW_PRESSED,
        DOWN_ARROW_PRESSED,
        CONTROL_KEY_PRESSED,
        SHIFT_KEY_PRESSED,
        SPACE_BAR_PRESSED
    }AppInputType;

    /// \brief enum used to indicate rendering platform
    typedef enum
    {
        RENDER_WITH_DX9,
        RENDER_WITH_DX11
    }RenderingPlatform;

    // ========== LIFECYCLE ========== //
    /// \brief Constructor
    AppLogic(Render::IWinWindow* window, const RenderingPlatform &platform);

    /// \brief Destructor
    virtual ~AppLogic(void);
    // ========== OVERLODED OPERATORS ========== //

    // ========== METHODS ========== //

    /// \brief starts the application to run
    void run();

    /// \brief stops the application
    void stop();
    
    /// \brief indicates user input
    void input(const AppInputType &input_type);
    
    // ========== GETTERS ========== //

    // ========== SETTERS ========== //

    // ========== INQUIRY ========== //
private:
    // ========== INTERNAL METHODS ========== //
    
    /// \brief switches the render devices between DX9 and DX11
    /// \details stops the main thread execution, releases resources and devices,
    /// and initializes things for the other platform and start the main thread again
    void switchRenderDevices();

    /// \brief initializes torus object, its mesh and texture, using the renderer
    /// \details first time creates the torus, other times changes its resources
    void initializeTorus(bool first_time);

    /// \brief main task function
    /// \details progress the torus model, and renders it
    static void main_task_function(void* user_data);

    // ========== ATTRIBUTES ========== //

    /// \brief the torus
    Torus* torus;

    /// \brief the renderer, abstract renderer
    Render::Renderer* renderer;

    /// \brief the main task
    Task* task;

    /// \brief semaphore used to synchronize with main task stop
    Semaphore* wait_stop_task_semaphore;

    /// \brief used to measure real time between task cycles
    TimeMeter* time_meter;

    /// \brief the app window
    Render::IWinWindow* window;

    /// \brief the current platform used
    RenderingPlatform current_rendering_platform;

    /// \brief arc ball camera theta
    float camera_theta;

    /// \brief arc ball camera phi
    float camera_phi;

    /// \brief arc ball camera radio
    float camera_radio;
};
};
#endif // _TORUSPRORENDERING_APPMODEL_APPLOGIC_H__
